package com.kyl.service;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.kyl.constant.SuperConstant;
import com.kyl.dto.DeptDto;
import com.kyl.entity.Dept;
import com.kyl.exception.BaseException;
import com.kyl.mapper.DeptMapper;
import com.kyl.utils.BeanConv;
import com.kyl.utils.EmptyUtil;
import com.kyl.utils.NoProcessing;
import com.kyl.vo.DeptVo;
import com.kyl.vo.TreeItemVo;
import com.kyl.vo.TreeVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author WanJl
 * @version 1.0
 * @title DeptService
 * @description 部门服务接口
 * @create 2025/1/6
 */
@Slf4j
@Service
public class DeptService {
    @Resource
    private DeptMapper deptMapper;


    @Resource
    private UserService userService;

    /**
     * 查询部门列表
     *
     * @param deptDto
     * @return
     */
    public List<DeptVo> findDeptList(DeptDto deptDto) {
        //查询Mapper
        List<Dept> list = deptMapper.selectList(deptDto);
        //把查询到Dept对象转换为VO对象
        List<DeptVo> deptVoList = BeanConv.toBeanList(list, DeptVo.class);
        //为对象里的每个createTime属性设置时间的格式
        deptVoList.forEach(v -> v.setCreateDay(LocalDateTimeUtil.format(v.getCreateTime(), "yyyy-MM-dd")));
        //返回集合
        return deptVoList;
    }

    /**
     * 新增部门
     *
     * @param deptDto
     * @return
     */
    @Transactional  //声明式事务，声明了这个注解后，这个方法里的操作必须全部成功，否则全部回滚。
    public Boolean createDept(DeptDto deptDto) {
        //1、转换：把DeptDto对象转换为Dept对象
        Dept dept = BeanUtil.toBean(deptDto, Dept.class);
        //2、dept里的部门编号需要写，需根据父部门的编号，创建当前部门的编号
        String deptNo = createDeptNo(deptDto.getParentDeptNo());
        dept.setDeptNo(deptNo);
        //3、执行mapper的保存方法
        int flag = deptMapper.insert(dept);
        if (flag != 1) {
            throw new RuntimeException("新增部门出错");
        }
        //4、如果当前的leader也是其他部门的负责人，那么则清空其他部门的leader数据
        if (ObjectUtil.isNotEmpty(deptDto.getLeaderId())) {
            //根据leaderId查询，查询是否存在其他部门，存在则删除
            deptMapper.clearOtherDeptLeader(deptDto.getLeaderId(), deptNo);
            //在用户表中设置标识，标识该用户为当前部门的leader
            userService.updateIsLeaderByUserIdAndDeptNo(deptDto.getLeaderId(), dept.getDeptNo());
        }
        return true;
    }

    /**
     * 根据父部门编号创建部门编号
     *
     * @param parentDeptNo
     * @return
     */
    public String createDeptNo(String parentDeptNo) {
        //1、根据父部门编号，创建部门编号
        //检查，超过4级部门就抛异常
        if (NoProcessing.processString(parentDeptNo).length() / 3 == 5) {
            throw new BaseException("部门最多4级");
        }
        //构建查询的条件，查找父部门编号对象的子部门
        DeptDto deptDto = DeptDto.builder()
                .parentDeptNo(parentDeptNo)
                .build();
        List<Dept> deptList = deptMapper.selectList(deptDto);
        //判断是否有下属部门，没有则创建下属部门编号
        if (EmptyUtil.isNullOrEmpty(deptList)) {
            //创建并返回下属部门编号
            return NoProcessing.createNo(parentDeptNo, false);//-----
        } else {//如果有下属部门，就新编号就在已有部门编号后累加
            //先找到父部门下编号最大的子部门编号，然后生成新的编号。
            Long deptNo = deptList.stream()
                    .map(dept -> Long.valueOf(dept.getDeptNo()))
                    //获取最大值。Comparator.comparing(i -> i)是一个比较器，比较最大的值
                    .max(Comparator.comparing(i -> i)).get();
            //创建节点编号
            return NoProcessing.createNo(String.valueOf(deptNo), true);
        }
    }

    /**
     * 修改部门
     *
     * @param deptDto
     * @return
     */
    @Transactional
    public Boolean updateDept(DeptDto deptDto) {
        //1、转换：把DeptDto对象转换为Dept对象
        Dept dept = BeanUtil.toBean(deptDto, Dept.class);

        //2、先验证是否能够修改，
        // 当前部门存在下属部门，则修改要考虑是否禁用。
        // 当前部门存在员工，不能禁用
        if (dept.getDataState().equals(SuperConstant.DATA_STATE_1)) {
            //部门存在下属部门，则修改要考虑是否禁用
            if (hasChildByDeptId(dept.getDeptNo())) {
                throw new RuntimeException("存在下属部门，不能禁用");
            }
            //当前部门存在员工，不能禁用
            if (checkDeptExistUser(dept.getDeptNo())) {
                throw new RuntimeException("存在员工，不能禁用");
            }
        }

        //3、执行修改
        int flag = deptMapper.updateByPrimaryKey(dept);
        if (flag == 0) {
            throw new RuntimeException("修改部门出错");
        }
        //4、如果当前的leader也是其他部门的负责人，那么则清空其他部门的leader数据
        if (ObjectUtil.isNotEmpty(deptDto.getLeaderId())) {
            //根据leaderId查询，查询是否存在其他部门，存在则删除
            deptMapper.clearOtherDeptLeader(deptDto.getLeaderId(), deptDto.getDeptNo());
            //在用户表中设置标识，标识该用户为当前部门的leader
            userService.updateIsLeaderByUserIdAndDeptNo(deptDto.getLeaderId(), dept.getDeptNo());
        }

        return true;
    }

    public boolean checkDeptExistUser(String deptNo) {
        int result = deptMapper.checkDeptExistUser(deptNo);
        return result > 0 ? true : false;
    }

    public boolean hasChildByDeptId(String deptNo) {
        int result = deptMapper.hasChildByDeptId(deptNo);
        return result > 0 ? true : false;
    }

    /**
     * 删除部门
     *
     * @param deptId
     * @return
     */
    public Boolean removeDept(String deptId) {

            //部门存在下属部门，则修改要考虑是否删除
            if (hasChildByDeptId(deptId)) {
                throw new RuntimeException("存在下属部门，不能删除");
            }
            //当前部门存在员工，不能删除
            if (checkDeptExistUser(deptId)) {
                throw new RuntimeException("存在员工，不能删除");
            }
            //删除岗位，回去把岗位的删除功能写完后，把这加上
            // .......

        return deptMapper.deleteByDeptNo(deptId)>0?true:false;
    }

    /**
     * 启用-禁用部门
     *
     * @param deptDto
     * @return
     */
    public Boolean isEnableDept(DeptDto deptDto) {
        //查询部门
        Dept dept=deptMapper.selectByDeptNo(deptDto.getDeptNo());
        if (BeanUtil.isEmpty(dept)){
            throw new RuntimeException("部门不存在");
        }
        //设置状态
        dept.setDataState(deptDto.getDataState());

        //修改部门
        int result = deptMapper.updateByPrimaryKey(dept);
        if (result==0) throw new RuntimeException("修改部门出错");
        return true;
    }

    /**
     * 树形展示
     *
     * @return
     */
    public TreeVo deptTreeVo() {
        //0、通过根节点查询树形结构
        String parentDeptNo = SuperConstant.ROOT_DEPT_PARENT_ID;
        //构建查询条件
        DeptDto deptDto = DeptDto.builder()
                .dataState(SuperConstant.DATA_STATE_0)
                .parentDeptNo(NoProcessing.processString(parentDeptNo))
                .build();

        //1、根据条件查询部门列表
        List<Dept> deptList = deptMapper.selectList(deptDto);
        //1.5 判空
        if (EmptyUtil.isNullOrEmpty(deptList))
            throw new RuntimeException("部门数据没定义！");
        //2、把列表[数组]转换成树形结构
        List<TreeItemVo> treeItemList = new ArrayList<>();

        //2.1 确定根节点
        Dept deptRoot = deptList.stream()
                .filter(dept -> SuperConstant.ROOT_DEPT_PARENT_ID.equals(dept.getParentDeptNo()))
                .collect(Collectors.toList()).get(0);

        //集合操作，两个集合，求交集、并集、差集....一个集合，过滤、排序、分组、映射、求和、求平均值....
        //把一个Dept集合里的所有Dept对象转换成另一个类型的对象。

        //2.2 递归调用，转换为树形
        recursionTreeItem(treeItemList, deptRoot, deptList);

        //3、返回树形结构
        return TreeVo.builder()
                .items(treeItemList)
                .build();
    }

    /**
     * 把列表转换为树形结构
     *
     * @param treeItemList 树形结构列表---最多4层部门
     * @param deptRoot     根节点
     * @param deptList     部门列表
     */
    private void recursionTreeItem(List<TreeItemVo> treeItemList, Dept deptRoot, List<Dept> deptList) {
        //1、先构建TreeItemVo对象。
        TreeItemVo treeItemVo = TreeItemVo.builder()
                .id(deptRoot.getDeptNo())
                .label(deptRoot.getDeptName())
                .build();
        //2、获取当前部门下的子部门
        List<Dept> childrenDept = deptList.stream()
                .filter(dept -> dept.getParentDeptNo().equals(deptRoot.getDeptNo()))
                .collect(Collectors.toList());

        //如果子部门不为空，则继续递归调用
        if (!EmptyUtil.isNullOrEmpty(childrenDept)) {
            //子部门的列表
            List<TreeItemVo> listChildren = new ArrayList<>();

            //继续找子部门，直到找不到为止
            childrenDept.forEach(dept -> this.recursionTreeItem(listChildren, dept, deptList));

            //为部门添加子部门
            treeItemVo.setChildren(listChildren);
        }
        //为树形结构添加最终的节点部门
        treeItemList.add(treeItemVo);
    }

    public List<DeptVo> findDeptInDeptNos(List<String> deptNos) {
        List<Dept> list= deptMapper.findDeptInDeptNos(deptNos);
        log.info("查询部门结果：{}",list);
        return BeanConv.toBeanList(list,DeptVo.class);
    }

    public List<DeptVo> findDeptVoListInRoleId(List<Long> roleIdSet) {
        return null;
    }
}
